/* Copyright © 2010 LPRM
Universidade Federal do Espírito Santo - RNP-GT CWTools

This file is part of JoinUs!.

JoinUs! is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

JoinUs! is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with JoinUs!. If not, see <http://www.gnu.org/licenses/>. */
package br.ufes.cwtools.joinus.home.campaigns;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Vector;

import org.xml.sax.InputSource;

import br.ufes.cwtools.joinus.home.core.Campaign;
import br.ufes.cwtools.joinus.home.map.ShowArea;
import br.ufes.cwtools.joinus.util.ServerCom;

import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import br.ufes.cwtools.joinus.R;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

public class CampaignListView extends ListActivity {

	private static final int RESULT_CREATE = 1;

	private class NewCampaign {
		String name;
		String creator;
		public int latitude;
		public int longitude;
		public int radius;
		public long id;

		public NewCampaign(String name, String creator) {
			this.name = name;
			this.creator = creator;
		}

		@Override
		public String toString() {
			return this.name;
		}
	}

	private ArrayList<NewCampaign> campaigns;
	private CampaignAdapter adapter;
	NewCampaign activeCampaign;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setTitle("JoinUs - Campaigns");
		setContentView(R.layout.campaign_view);
		campaigns = new ArrayList<NewCampaign>();
		adapter = new CampaignAdapter(this, R.layout.campaign_list_item,
				campaigns);
		setListAdapter(adapter);

		loadData(); // Carrega as campanhas a partir do servidor.

		getListView().setOnItemClickListener(new OnItemClickListener() {
			// @Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				/*
				 * Ao clicar numa campanha da lista, torna as informações da
				 * campanha selecionada e opções adicionais visiveis e esconde
				 * as informações das demais campanhas.
				 */
				ArrayList<NewCampaign> items = adapter.GetItems();
				activeCampaign = items.get(position);
				View v = view.findViewById(R.id.campaign_creator);
				if (v != null) {
					if (v.getVisibility() != View.VISIBLE) {
						collapseAll();
						toggleDetails(view, View.VISIBLE);
					} else {
						// Se a campanha estava visivel, então esconde.
						toggleDetails(view, View.GONE);
					}
				}
			}
			/*
			 * Nota importante: o clique não funciona se a view contiver algum
			 * elemento com atributo android:focusable="true" (um botão, por
			 * exemplo); deve-se definir explicitamente como "false" no xml.
			 */
		});
	}

	/**
	 * Esconde todas informações adicionais das campanhas, deixando apenas o
	 * nome de cada campanha visivel na lista.
	 */
	private void collapseAll() {
		int count = getListView().getChildCount();
		for (int i = 0; i < count; ++i) {
			View v = getListView().getChildAt(i);
			toggleDetails(v, View.GONE);
		}
	}

	private static void toggleDetails(View view, int visibility) {
		if (view == null)
			return;
		View v;

		v = view.findViewById(R.id.campaign_creator);
		if (v != null)
			v.setVisibility(visibility);

		v = view.findViewById(R.id.campaign_expiration_date);
		if (v != null)
			v.setVisibility(visibility);

		v = view.findViewById(R.id.campaign_button_map);
		if (v != null)
			v.setVisibility(visibility);
		
		v = view.findViewById(R.id.chat);
		if (v != null)
			v.setVisibility(visibility);

		v = view.findViewById(R.id.campaign_button_participants);
		if (v != null)
			v.setVisibility(visibility);

		v = view.findViewById(R.id.campaign_button_leave);
		if (v != null)
			v.setVisibility(visibility);
	}

	private class CampaignAdapter extends ArrayAdapter<NewCampaign> {
		private ArrayList<NewCampaign> items;
		
		public ArrayList<NewCampaign> GetItems(){
			return items;
		}

		public CampaignAdapter(Context context, int textViewResourceId,
				ArrayList<NewCampaign> items) {
			super(context, textViewResourceId, items);
			this.items = items;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View v = convertView;
			if (v == null) {
				LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				v = vi.inflate(R.layout.campaign_list_item, null);
			}
			NewCampaign campaign = items.get(position);
			if (campaign != null) {
				((TextView) v.findViewById(R.id.campaign_name))
						.setText(campaign.name);
				((TextView) v.findViewById(R.id.campaign_creator))
						.setText("Creator: " + campaign.creator);
				((TextView) v.findViewById(R.id.campaign_expiration_date))
						.setText(""); // TODO

				toggleDetails(v, View.GONE); // Esconde a visualização dos
												// detalhes da campanha.
			}
			return v;
		}
	}

	private class DateHelper {
		/*
		 * TODO: Se livrar dessa classe e arrumar uma forma mais inteligente de
		 * filtrar as campanhas já finalizadas. Se as datas forem validadas e
		 * formatadas adequadamente ao inserir no banco (ex. yyyy-MM-dd
		 * HH:mm:ss), bastará uma comparação de String.
		 */
		private int year, month, day, hour, minute, second;

		public DateHelper() {
			Calendar c = Calendar.getInstance();
			this.year = c.get(Calendar.YEAR);
			this.month = 1 + c.get(Calendar.MONTH);
			this.day = c.get(Calendar.DAY_OF_MONTH);
			this.hour = c.get(Calendar.HOUR_OF_DAY);
			this.minute = c.get(Calendar.MINUTE);
			this.second = c.get(Calendar.SECOND);
		}

		public boolean isFuture(String date) {
			date = date.replaceAll("[^0-9]", " ");
			String[] sd = date.split(" ");

			int year, month, day, hour, minute, second;
			year = Integer.parseInt(sd[0]);
			month = Integer.parseInt(sd[1]);
			day = Integer.parseInt(sd[2]);
			hour = Integer.parseInt(sd[3]);
			minute = Integer.parseInt(sd[4]);
			second = Integer.parseInt(sd[5]);

			if (year != this.year)
				return this.year < year;
			if (month != this.month)
				return this.month < month;
			if (day != this.day)
				return this.day < day;
			if (hour != this.hour)
				return this.hour < hour;
			if (minute != this.minute)
				return this.minute < minute;
			return this.second < second;
		}
	}

	private void loadData() {
		adapter.clear();

		Bundle bundle = this.getIntent().getExtras();
		String username = bundle.getString("username");
		String password = bundle.getString("password");

		String xml = ServerCom.getUpdates(username, password);
		if (xml == null) {
			Log.d("CampaignListView.loadData()", "Failed to load campaign data---null xml.");
			return;
		}

		SQLiteDatabase database = this.openOrCreateDatabase("homedb", MODE_PRIVATE, null);

		InputSource is = new InputSource();
		is.setCharacterStream(new StringReader(xml));
		Vector<Campaign> tempCampaigns = (new Campaign()).fromXml(is);
		for (Campaign c : tempCampaigns) {
			database.execSQL("UPDATE activeCamp SET status=1" + " WHERE id="
					+ c.getId() + " AND user='" + username + "';");
		}

		DateHelper dh = new DateHelper();

		Cursor query = database.query("activeCamp", null, "user='" + username
				+ "'", null, null, null, null);
		int count = query.getCount();
		for (int i = 0; i < count; ++i) {
			query.moveToPosition(i);
			String name = query.getString(query.getColumnIndex("campName"));
			String creator = query.getString(query.getColumnIndex("authorName"));

			String dateString = query.getString(query.getColumnIndex("expDate"));
			if (!dh.isFuture(dateString)) { // Verifica se a campanha terminou.
				continue;
			}

			NewCampaign campaign = new NewCampaign(name, creator);
			campaign.id = query.getInt(query.getColumnIndex("id"));
			campaign.latitude = query.getInt(query.getColumnIndex("lat"));
			campaign.longitude = query.getInt(query.getColumnIndex("lon"));
			campaign.radius = query.getInt(query.getColumnIndex("radius"));

			adapter.add(campaign);

			/*
			 * Tabela: activeCamp (id INTEGER, lat INTEGER, lon INTEGER, radius
			 * INTEGER, user TEXT NOT NULL, campName TEXT NOT NULL, authorName
			 * TEXT, desc TEXT, expDate TEXT, status INTEGER NOT NULL, public
			 * INTEGER, PRIMARY KEY (id, user))
			 */
		}
		query.close();
		database.close();
	}

	/**
	 * Método onClick chamado pelo botão de criar uma nova campanha.
	 * 
	 * @param view
	 */
	public void createCampaign(View view) {
		Intent i = new Intent(getApplicationContext(),
				CampaignCreateActivity.class);
		i.putExtras(this.getIntent()); // Inclui os extras para passar o
										// username e password.
		// startActivity(i);
		startActivityForResult(i, RESULT_CREATE);
	}

	public void showMapOnClick(View view) {
		Intent i = new Intent(getApplicationContext(), ShowArea.class);
		i.putExtra("id", activeCampaign.id);
		i.putExtra("lat", activeCampaign.latitude);
		i.putExtra("lon", activeCampaign.longitude);
		i.putExtra("radius", activeCampaign.radius);
		startActivity(i);
	}
	
	public void ChatManagerOnClick(View view) {
		Intent i = new Intent(getApplicationContext(), ChatManager.class);
		i.putExtra("campaignId", activeCampaign.id);
		startActivity(i);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		if (requestCode == RESULT_CREATE) {
			loadData();
		}
	}
}
